#pragma once
#include "Common.hpp"
#include "Socket.hpp"
#include "InetAddr.hpp"
#include <functional>
#include <memory>

using service_t =  std::function<void(std::unique_ptr<Socket>&, InetAddr&)>;

class Tcpserver{
public:
	Tcpserver(uint16_t port, service_t service)
	:_port(port),
	_service(service)
	{
		_listensock = std::make_unique<TcpSocket>();
		_listensock->BulidTcpSocketMethod(port);
		_isrunning = false;
	}

	void Start(){
		_isrunning = true;
		while(_isrunning){
			InetAddr client;
			auto sock = _listensock->Accept(&client);
			if(sock == nullptr){
				continue;
			}

			pid_t pid = fork();
			if(pid < 0){
				LOG(LogLevel::FATAL)<<"fork error";
				exit(FORK_ERR);
			}
			else if(pid == 0){
				_listensock->Close();
				if(fork() > 0){
					exit(0);
				}

				_service(sock, client);
				exit(SUCESS);
			}
			else{
				sock->Close();
				int n = waitpid(pid, nullptr, 0);
				(void)n;
			}
		}


		_isrunning =false;
	}

	~Tcpserver(){
		if(_listensock){
			_listensock->Close();
		}
	}

private:
	uint16_t _port;
	std::unique_ptr<Socket> _listensock;
	bool _isrunning;
	service_t _service;
};